﻿using System;
using System.Collections.Generic;
using System.Linq;
using Metro.Kashikoi.Common.ExceptionHandling;
using Metro.Kashikoi.Service.Common.Entity;
using Metro.Kashikoi.ServiceContract.Storage;

namespace Metro.Kashikoi.Service.Storage.Entity
{
    /// <summary>
    /// 
    /// </summary>
    public static class Repository
    {
        #region Extension Methods

        /// <summary>
        /// Gets the inventory by id.
        /// </summary>
        /// <param name="repository">The repository.</param>
        /// <param name="id">The id.</param>
        /// <returns>The inventory.</returns>
        public static BinInventory GetInventoryById(this Repository<Inventory> repository, int id)
        {
            var inventory = repository.GetInventory(o => o.Id == id && o.Deleted == false);
            if (inventory == null)
            {
                throw new NotExistException
                {
                    Entity = "Inventory",
                    Value = id
                };
            }
            return inventory;
        }

        /// <summary>
        /// Gets the inventory by SSID.
        /// </summary>
        /// <param name="repository">The repository.</param>
        /// <param name="SSID">The SSID.</param>
        /// <returns>The inventory.</returns>
        public static BinInventory GetInventoryBySSID(this Repository<Inventory> repository, string SSID)
        {
            var inventory = repository.GetInventory(o => o.SSID == SSID && o.Deleted == false);
            if (inventory == null)
            {
                throw new NotExistException
                {
                    Entity = "Inventory",
                    Property = "SSID",
                    Value = SSID,
                };
            }
            return inventory;
        }

        /// <summary>
        /// Gets the inventory.
        /// </summary>
        /// <param name="repository">The repository.</param>
        /// <param name="predicate">The predicate.</param>
        /// <returns>
        /// The inventory.
        /// </returns>
        public static BinInventory GetInventory(this Repository<Inventory> repository,
            Func<BinInventory, bool> predicate)
        {
            var query = repository.GetQuery().OfType<BinInventory>();

            if (query.Count(predicate) == 1)
            {
                return query.Single(predicate);
            }
            else
            {
                return null;
            }
        }

        /// <summary>
        /// Deletes the inventories.
        /// </summary>
        /// <param name="repository">The repository.</param>
        /// <param name="predicate">The predicate.</param>
        public static void DeleteInventories(this Repository<Inventory> repository,
            Func<Inventory, bool> predicate)
        {
            var inventories = repository.Where(predicate);
            foreach (var inventory in inventories)
            {
                inventory.Deleted = true;
                (inventory as BinInventory).Container.Deleted = true;
                (inventory as BinInventory).Trigger.Deleted = true;
            }
        }

        /// <summary>
        /// Gets the inventories.
        /// </summary>
        /// <param name="repository">The repository.</param>
        /// <param name="predicate">The predicate.</param>
        /// <returns>A lisf ot inventory.</returns>
        public static IList<BinInventory> GetInventories(
            this Repository<Inventory> repository, Func<BinInventory, bool> predicate)
        {
            var inventories = repository.Where<BinInventory>(predicate);
            return inventories.ToList();
        }

        #endregion

        #region Private Methods

        //private static Container GetContainer(IUnitOfWork context, int inventoryId)
        //{
        //    var rep = new Repository<Container>(context);
        //    if (rep.Count(o => o.Inventory.Id == inventoryId) == 1)
        //    {
        //        return rep.Single(o => o.Inventory.Id == inventoryId);
        //    }
        //    else
        //    {
        //        return null;
        //    }
        //}

        //private static Trigger GetTrigger(IUnitOfWork context, int inventoryId)
        //{
        //    var rep = new Repository<Trigger>(context);
        //    if (rep.Count(o => o.Inventory.Id == inventoryId) == 1)
        //    {
        //        return rep.Single(o => o.Inventory.Id == inventoryId);
        //    }
        //    else
        //    {
        //        return null;
        //    }
        //}

        //public static void DeleteTrigger(IUnitOfWork context, BinInventory entity)
        //{
        //    if (entity != null && entity.Trigger != null)
        //    {
        //        var rep = new Repository<Trigger>(context);
        //        rep.Remove(entity.Trigger);
        //    }
        //}

        //public static void DeleteContainer(IUnitOfWork context, BinInventory entity)
        //{
        //    if (entity != null && entity.Container != null)
        //    {
        //        var rep = new Repository<Container>(context);
        //        rep.Remove(entity.Container);
        //    }
        //}
        #endregion
    }
}
